package com.cd.university.config.security.authentication;

import com.cd.university.common.RestResult;
import com.cd.university.common.utils.IpUtils;
import com.cd.university.common.utils.JwtUtils;
import com.cd.university.common.utils.SpringUtil;
import com.cd.university.config.security.properties.SecurityProperties;
import com.cd.university.db.mapper.RoleMapper;
import com.cd.university.db.mapper.RolePermissionMapper;
import com.cd.university.db.mapper.UserLoginLogMapper;
import com.cd.university.db.pojo.User;
import com.cd.university.db.pojo.UserLoginLog;
import com.cd.university.service.PermissionService;
import com.cd.university.service.RoleService;
import com.cd.university.service.UserService;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.Date;

/**
 * 登陆成功处理器
 * @author 陈栋
 * @create 2021/9/3 18:42
 */
@Component
public class CdAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

    /**
     * 日志打印
     */
    private Logger logger = LoggerFactory.getLogger(getClass());

    private ObjectMapper objectMapper = new ObjectMapper();

    /**
     * UserDetailsService
     */
    @Autowired
    private UserDetailsService userDetailsService;

    /**
     * Jwt工具类
     */
    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private SecurityProperties securityProperties;

    /**
     * redis操控该工具
     */
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private PermissionService permissionService;

    @Autowired
    private UserService userService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private UserLoginLogMapper userLoginLogMapper;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request,
                                        HttpServletResponse response,
                                        Authentication authentication) throws ServletException, IOException {
        User user = null;
        UserDetails userDetails = null;

        if (authentication instanceof UsernamePasswordAuthenticationToken) {

            String username = authentication.getName();
            userDetails = userDetailsService.loadUserByUsername(username);
            user = getUserByUserInfo(username);
        }else {
            String info = authentication.getName();
            user = getUserByUserInfo(info);
            userDetails = userDetailsService.loadUserByUsername(info);
        }

        // 设置用户密码不可见
        user.setPassword("Invisible");
        // 获得用户角色
        String roleName = roleService.searchRoleName(user.getRoleId());

        // 往响应头里面放用户token
        String accessToken = jwtUtils.createAccessToken(userDetails);
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write(objectMapper.writeValueAsString(
                RestResult.success("登陆成功")
                .put("data", user)
                .put("roleName",roleName)
                .put("permissionList",permissionService.searchPermissionByRoleId(user.getRoleId()))
                .put(securityProperties.getJwt().getHeader(), accessToken)
        ));

        // 往缓存中放入刷新Token
        String redisToken = jwtUtils.createRedisToken(userDetails);
        redisTemplate.opsForHash().put(securityProperties.getJwt().getHeader(),
                String.valueOf(user.getUserId()),
                redisToken);

        // 记录用户登录日志
        insertUserLoginLog(user.getUserId(),user.getUsername(),user.getUserRealname(),request);
    }

    private User getUserByUserInfo(String info) {
        return userService.searchUserByUserInfo(info);
    }

    @Async
    public void insertUserLoginLog(Integer userid,
                                   String username,
                                   String userRealName,
                                   HttpServletRequest request) {
        Date loginTime = new Date(System.currentTimeMillis());
        String ipAddress = IpUtils.getIPAddress(request);
        UserLoginLog userLoginLog = new UserLoginLog(loginTime, userid, username, userRealName, ipAddress);

        // 将用户的登录日志插入数据库中
        userLoginLogMapper.insertSelective(userLoginLog);
    }
}
